package io.gitee.zhangbinhub.admin.oauth.component

import io.gitee.zhangbinhub.acp.boot.interfaces.LogAdapter
import io.gitee.zhangbinhub.acp.core.common.CommonTools
import io.gitee.zhangbinhub.admin.common.constant.RoleCode
import io.gitee.zhangbinhub.admin.oauth.constant.OauthConstant
import io.gitee.zhangbinhub.admin.oauth.domain.ModuleFuncDomain
import io.gitee.zhangbinhub.admin.oauth.domain.RuntimeConfigDomain
import io.gitee.zhangbinhub.admin.oauth.domain.UserDomain
import io.gitee.zhangbinhub.admin.oauth.entity.User
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.security.core.GrantedAuthority
import org.springframework.security.core.authority.SimpleGrantedAuthority
import org.springframework.security.oauth2.core.OAuth2AuthenticationException
import org.springframework.security.oauth2.core.OAuth2Error
import org.springframework.security.oauth2.core.OAuth2ErrorCodes
import org.springframework.stereotype.Component

/**
 * @author zhangbin by 11/04/2018 15:19
 * @since JDK 11
 */
@Component
class AuthUserService @Autowired
constructor(
    private val logAdapter: LogAdapter,
    private val userDomain: UserDomain,
    private val moduleFuncDomain: ModuleFuncDomain,
    private val runtimeConfigDomain: RuntimeConfigDomain
) {
    /**
     * 根据 username 获取用户信息
     *
     * @param username 用户名
     * @return 用户对象
     * @throws OAuth2AuthenticationException 找不到用户信息异常
     */
    @Throws(OAuth2AuthenticationException::class)
    fun loadUserByUsername(username: String): User = userDomain.getUserInfoByLoginNo(username, true)
        ?: throw OAuth2AuthenticationException(
            OAuth2Error(
                OAuth2ErrorCodes.INVALID_REQUEST,
                "无此用户：$username",
                null
            )
        )

    fun loadUserAuthorities(user: User): Set<GrantedAuthority> = mutableSetOf<GrantedAuthority>().apply {
        user.roleSet.forEach { role ->
            this.add(SimpleGrantedAuthority(RoleCode.prefix + role.code)) //角色编码
        }
        moduleFuncDomain.getModuleFuncList(user.id).forEach { module ->
            this.add(SimpleGrantedAuthority(module.code)) //模块功能编码
        }
    }

    /**
     * 记录用户密码错误次数
     */
    @Throws(OAuth2AuthenticationException::class)
    fun storePasswordErrorTime(username: String) = userDomain.storePasswordErrorTime(username).let {
        runtimeConfigDomain.findByName(OauthConstant.passwordErrorTime)?.let { runtimeConfig ->
            if (runtimeConfig.enabled && !CommonTools.isNullStr(runtimeConfig.value)) {
                runtimeConfig.value!!.toInt().let { maxPasswordErrorTime ->
                    if (maxPasswordErrorTime in 1..it) {
                        userDomain.getUserInfoByLoginNo(username)?.apply {
                            this.enabled = false
                            userDomain.doSaveUser(this)
                        }
                        logAdapter.error("错误次数达${maxPasswordErrorTime}次，账号已禁用，请联系系统管理员！")
                        throw OAuth2AuthenticationException(
                            OAuth2Error(
                                OAuth2ErrorCodes.INVALID_REQUEST,
                                "错误次数达${maxPasswordErrorTime}次，账号已禁用，请联系系统管理员！",
                                null
                            )
                        )
                    }
                }
            }
        }
    }

    /**
     * 清除用户密码错误次数
     */
    fun clearPasswordErrorTime(username: String) = userDomain.clearPasswordErrorTime(username)
}
